package com.morrislabs.facebook
{
    import com.facebook.Facebook;
    import com.facebook.commands.friends.AreFriends;
    import com.facebook.commands.friends.GetFriends;
    import com.facebook.commands.users.GetInfo;
    import com.facebook.data.friends.AreFriendsData;
    import com.facebook.data.friends.FriendsCollection;
    import com.facebook.data.friends.FriendsData;
    import com.facebook.data.friends.GetFriendsData;
    import com.facebook.data.users.FacebookUser;
    import com.facebook.data.users.FacebookUserCollection;
    import com.facebook.data.users.GetInfoData;
    import com.facebook.data.users.GetInfoFieldValues;
    import com.facebook.events.FacebookEvent;
    import com.facebook.net.FacebookCall;
    
    import flash.display.LoaderInfo;
    
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;
	
		
	public class FacebookImport
	{
		private var user:FacebookUser;
		private var fbook:Facebook;
		
		private var fbLoaderInfo:LoaderInfo;
		private var fbLogin:FacebookLogin;
		
		private var _callbackAfterLoad: Function;
		
		private var userName:String;
		
        [Bindable]
        public var errorMessage:String;		
		
		[Bindable]
		private var friends:ArrayCollection = new ArrayCollection();
		private var coefficient:Array;
		private var fuid1:Array = new Array();
		private var fuid2:Array = new Array();					

		private var xmlData:XML = new XML();
		private var xmlFriendArray:XML = new XML();
		private var xmlRelationArray:XML = new XML();
			
				
		public function FacebookImport(fbl:LoaderInfo, callback:Function=null)
		{
			fbLoaderInfo = fbl;
			
			if (callback != null)
				this.callbackAfterLoad = callback;
		}
		

		public function get callbackAfterLoad():Function 
		{ 
			return this._callbackAfterLoad; 
		}
		public function set callbackAfterLoad(f:Function):void 
		{ 
			this._callbackAfterLoad = f; 
		}
		
				
		
		public function importFriends():void
		{
			if (!fbLogin)
				fbLogin = new FacebookLogin();
			
			if( !fbLogin.isConnected() ) 
			{
				// after connecting, the login
				// will call getFriensData
				fbLogin.connect(fbLoaderInfo, this.getFriendsData);
			}
			else {
				// call it directly
				getFriendsData();
			}
		}	

		public function getFriendsData():void
		{
			fbook = fbLogin.getHandle();
			
			var call1:FacebookCall = fbook.post(new GetInfo([fbook.uid], ['first_name', 'last_name']));
			call1.addEventListener(FacebookEvent.COMPLETE, handleGetInfoResponse);

			 var call2:FacebookCall = fbook.post(new GetFriends(null, fbook.uid));
			call2.addEventListener(FacebookEvent.COMPLETE, onGetFriends);
		}
		
		private function resetGraph():void
		{
			friends.removeAll();
			fuid1.splice(0, fuid1.length);
			fuid2.splice(0, fuid2.length);
			
		}			
		
		private function handleGetInfoResponse(e:FacebookEvent):void 
		{
			var responseData:GetInfoData = e.data as GetInfoData;
			
			if (!responseData || e.error){ // an error occurred
				Alert.show(e.error.errorMsg);
				return;
			}
			
			var firstName:String = responseData.userCollection.getItemAt(0).first_name;
			var lastName:String = responseData.userCollection.getItemAt(0).last_name;
			
			userName = firstName + " " + lastName;
			
			if(userName.length > 1) 
			{
				//Alert.show("Welcome " + userName + ", your graph is redrawing now...");
		 	} else {
		 		Alert.show("Couldn't get user info");
		 	}			
		}
		

		private function onGetFriends(e:FacebookEvent):void
		{
			var friendsUid:Array = new Array();
			var responseData:GetFriendsData = e.data as GetFriendsData;
			var users:FacebookUserCollection = responseData.friends;
			
			fuid1.splice(0, fuid1.length);
			fuid2.splice(0, fuid2.length);
			
						
			if (!responseData || e.error){			
				Alert.show(e.error.errorMsg);
				return;
			}		
			
			if (!users){			
				Alert.show("Cannot create UserCollection.friends");
				return;
			}		
					
			friendsUid.push(fbook.uid);
									
			for(var i:int; i < users.length; i++)
			{
				friendsUid.push((users.getItemAt(i) as FacebookUser).uid);
				
 				for(var n:int = i+1; n < users.length; n++)
				{	
   					fuid1.push((users.getItemAt(i) as FacebookUser).uid);
   					fuid2.push((users.getItemAt(n) as FacebookUser).uid);
 				}						 
			}
			var call:FacebookCall = fbook.post(new GetInfo(friendsUid, [GetInfoFieldValues.ALL_VALUES]));
			

			call.addEventListener(FacebookEvent.COMPLETE, onGetInfo);
			
		}
		
		private function onGetInfo(e:FacebookEvent):void
		{
			var users:FacebookUserCollection = (e.data as GetInfoData).userCollection;

			friends.removeAll();
			
			xmlData = <community id="facebook" title="FaceBook Friends"></community>
			xmlFriendArray =  <friendArray></friendArray>
			xmlRelationArray =  <relationArray></relationArray>
			
			//addFriend(fbook.uid, userName);
			
			for(var i:int = 0; i < users.length; i++)
			{
				friends.addItem(users.getItemAt(i));
				addFriend((friends[i] as FacebookUser).uid);
			}
			
			xmlData = xmlData.appendChild(xmlFriendArray);
			
			var call2:FacebookCall = fbook.post(new AreFriends(fuid1, fuid2));
			call2.addEventListener(FacebookEvent.COMPLETE, onGetAreFriends);
		}
				
		
		private function onGetAreFriends(e:FacebookEvent):void
		{
			var friend_users:FriendsCollection = (e.data as AreFriendsData).friendsCollection;
			var i:int;

			fuid1.splice(0, fuid1.length);
			fuid2.splice(0, fuid2.length);
			
			for(i = 0; i<friend_users.length; i++)
			{
				with ((friend_users.getItemAt(i) as FriendsData))
				{
					if(are_friends) 
					{
						addRelation(uid1.toString(), uid2.toString());
						fuid1.push(uid1.toString());
						fuid2.push(uid2.toString());
						//messagetext.text = messagetext.text + this.getFriendName(uid1.toString()) + 
						//						"+" + this.getFriendName(uid2.toString()) + ",";
					} 
				} 
			}	
			
			xmlData = xmlData.appendChild(xmlRelationArray);
			var fbu: FacebookUser;
			var numConnections:Array = new Array(friends.length);
			var maxConnections:int = 1;
			
			// set the vip factor
			for(i = 0; i < friends.length; i++)
			{
				fbu = (friends.getItemAt(i) as FacebookUser)
				
				numConnections[i] = 1;
				for(var n:int = 0; n < fuid1.length; n++)
				{
					if(fbook.uid != fuid1[n] && fbook.uid != fuid2[n] &&
					   (fbu.uid == fuid1[n] || fbu.uid == fuid2[n]))
					{   
						numConnections[i]++;
					}
				}
				
				if(i > 0 && numConnections[i] > maxConnections)
					maxConnections = numConnections[i];
			}
			
			var vip:Number;
			for(i = 1; i < friends.length; i++)
			{
				vip = (numConnections[i]/maxConnections);
				if(vip < 0.2)
					vip = 0.2;
				if(vip > 1.0)
					vip = 1.0;
						
				xmlData.*[0].*[i].@vipFactor = vip.toString();
			}
			
			
			// the XML is loaded, so start building the graph
			// communication to main app
			// method 1 - not good.  too tightly coupled
			//NthDegrees.getInstance().rebuildGraph(xmlData);
			
			// method 2:  better, but still coupled
			// since we need to know the callback function signature.
			// must have the signature:  public function F(XML):void
			//if (this.callbackAfterLoad != null)
			//	this.callbackAfterLoad.call(this, xmlData);
			
			// method 3:  best - just notify when the data is loaded
			// and pass the data thru the message delegator
			FacebookController.getInstance().dispatchEvent(
			      new FacebookMessage(FacebookMessage.XML_LOADED,{param1:xmlData}));
		}			
		
		private function addFriend(uID:String, uName:String = null):void
		{
			var name:String;
			
			if(!uName)
				name = this.getFriendName(uID);
			else
				name = uName;	
			
			var xmlFriendNode:XMLList = 
				XMLList('<friend id="'+uID+'" name="'+name+'" type="Friend" vipFactor="1.0"/>');
			
			xmlFriendArray = xmlFriendArray.appendChild(xmlFriendNode);
			
			if(uID != fbook.uid)
				addRelation(uID, fbook.uid);
		}
		
		private function addRelation(fromUID:String, toUID:String):void
		{
			var xmlRelationNode:XMLList = 
				XMLList('<relation id="x" fromID="'+fromUID+'" toID="'+toUID+'" bond="1"/>');
			
			xmlRelationArray = xmlRelationArray.appendChild(xmlRelationNode);			
		}		
		

		private function getFriendName(this_uid:String):String
		{
			for(var i:int = 0; i < friends.length; i++)
			{
				with((friends[i] as FacebookUser))
				{
					if(this_uid == uid)
					{
						return (first_name + " " + last_name);
					}
				}
			} 
			
			return (null);
		}

		public function getFriendUid(this_name:String):String
		{
			var sname:String;
			
			for(var i:int = 0; i < friends.length; i++)
			{
				with((friends[i] as FacebookUser))
				{
					sname = first_name + " " + last_name;
					if(this_name == sname)
					{
						return (uid);
					}
				}
			} 
			
			return (null);
		}			

		 

	}
}